home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 1996 #1
/
Amiga Plus CD - 1996 - No. 1.iso
/
pd
/
netz
/
xbtx_v1.1
/
gfxdisplay.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-26
|
31KB
|
1,423 lines
/*
** $Id: GfxDisplay.cpp 1.4 1995/09/26 19:45:11 olsen Exp olsen $
**
** :ts=4
*/
/*
* Amiga changes copyright © 1995 by Olaf Barthel, All Rights Reserved
*
* Copyright (c) 1992, 1993 Arno Augustin, Frank Hoering, University of
* Erlangen-Nuremberg, Germany.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* Erlangen-Nuremberg, Germany.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software has not been validated by the ``Bundesamt fuer Zulassungen in
* der Telekommunikation'' of the ``Deutsche Bundepost Telekom'' and thus
* must not be used for accessing the BTX-Network of the Telekom in Germany.
*
* Diese Software hat keine Zulassung durch das Bundesamt fuer Zulassungen in
* der Telekommunikation der Deutschen Bundespost Telekom und darf daher nicht
* am Netz der Deutschen Bundespost Telekom in Deutschland betrieben werden.
*/
#include "GfxDisplay.hpp"
#include "Attributes.h"
#include "RawKeys.h"
/****************************************************************************/
#include <graphics/modeid.h>
#include <hardware/blit.h>
#include <exec/execbase.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/keymap_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#ifdef __SASC
#include <pragmas/intuition_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/utility_pragmas.h>
#include <pragmas/keymap_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct ExecBase *SysBase;
extern struct DosLibrary *DOSBase;
extern struct Library *KeymapBase;
extern struct Library *UtilityBase;
#endif // __SASC
#include <string.h>
#include <stdio.h>
/****************************************************************************/
#define SPREAD(v) ((((ULONG)v) << 24) | (((ULONG)v) << 16) | (((ULONG)v) << 8) | ((ULONG)v))
GfxDisplay::GfxDisplay()
{
WORD i;
Screen = NULL;
Window = NULL;
for(i = 0 ; i < 60 ; i++)
Pen[i] = -1;
WaitingChar = -1;
memset(&LocalBitMap,0,sizeof(LocalBitMap));
memset(btx_font,0,sizeof(btx_font));
memset(fullrow_bg,0,sizeof(fullrow_bg));
cur_fg = -1;
cur_bg = -1;
}
GfxDisplay::~GfxDisplay()
{
Close();
}
VOID GfxDisplay::Close(VOID)
{
free_DRCS();
free_font_pixmaps();
FreeVec(LocalBitMap.Planes[0]);
if(Window)
{
EraseRect(RPort,Window->BorderLeft,Window->BorderTop,Window->Width - (Window->BorderRight+1),Window->Height - (Window->BorderBottom+1));
ReleaseColours();
CloseWindow(Window);
Window = NULL;
}
ReleaseColours();
if(Screen)
{
CloseScreen(Screen);
Screen = NULL;
}
}
VOID GfxDisplay::MonitorData(int *btx_rows,int *btx_fontheight)
{
rows = btx_rows;
fontheight = btx_fontheight;
}
LONG GfxDisplay::Open(STRPTR PubScreenName,int XScale,int YScale,BOOL Direct)
{
struct Screen *PubScreen;
DirectRender = Direct;
if(XScale < 1)
XScale = 1;
if(YScale < 1)
YScale = 1;
if(XScale > MAX_ZOOM)
XScale = MAX_ZOOM;
if(XScale > MAX_ZOOM)
XScale = MAX_ZOOM;
if(PubScreen = LockPubScreen((UBYTE *)PubScreenName))
{
VPort = &PubScreen -> ViewPort;
if(InitColours())
{
for(;;)
{
if(Window = OpenWindowTags(NULL,
WA_PubScreen, PubScreen,
WA_InnerWidth, 40 * FONT_WIDTH * XScale,
WA_InnerHeight, 20 * FONT_HEIGHT * YScale,
WA_RMBTrap, TRUE,
WA_IDCMP, IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_CLOSEWINDOW,
WA_DepthGadget, TRUE,
WA_CloseGadget, TRUE,
WA_DragBar, TRUE,
WA_Title, "xBTX",
WA_AutoAdjust, FALSE,
TAG_DONE))
break;
else
{
if(YScale > 1)
{
YScale = (YScale + 1) / 2;
continue;
}
if(XScale > 1)
{
XScale = (XScale + 1) / 2;
continue;
}
ReleaseColours();
break;
}
}
}
UnlockPubScreen(NULL,PubScreen);
}
if(!Window)
{
UWORD Pens = (UWORD)~0;
ULONG DisplayID;
DisplayID = FindBestModeID(
BIDTAG_NominalWidth, 40 * FONT_WIDTH * XScale,
BIDTAG_NominalHeight, 20 * FONT_HEIGHT * YScale,
BIDTAG_Depth, 8,
TAG_DONE);
if(DisplayID == INVALID_ID)
return(-1);
if(Screen = OpenScreenTags(NULL,
SA_Depth, 8,
SA_DisplayID, DisplayID,
SA_Overscan, OSCAN_TEXT,
SA_SharePens, TRUE,
SA_SysFont, 1,
SA_Interleaved, TRUE,
SA_AutoScroll, TRUE,
SA_Width, 40 * FONT_WIDTH * XScale,
SA_Height, 20 * FONT_HEIGHT * YScale,
SA_Pens, &Pens,
SA_Quiet, TRUE,
SA_ShowTitle, FALSE,
SA_Behind, TRUE,
TAG_DONE))
{
VPort = &Screen->ViewPort;
if(InitColours())
{
if(!(Window = OpenWindowTags(NULL,
WA_CustomScreen, Screen,
WA_Width, Screen->Width,
WA_Height, Screen->Height,
WA_Backdrop, TRUE,
WA_Borderless, TRUE,
WA_RMBTrap, TRUE,
WA_IDCMP, IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_CLOSEWINDOW,
TAG_DONE)))
{
CloseWindow(Window);
Window = NULL;
CloseScreen(Screen);
Screen = NULL;
}
}
else
{
CloseScreen(Screen);
Screen = NULL;
}
}
}
if(Window)
{
RPort = Window->RPort;
WindowPort = Window->UserPort;
WindowMask = 1UL << WindowPort->mp_SigBit;
FgPen = 0;
BgPen = 0;
SetABPenDrMd(RPort,Pen[FgPen],Pen[BgPen],JAM2);
DisplayWidth = (UWORD)(40 * FONT_WIDTH * XScale);
DisplayHeight = (UWORD)(20 * FONT_HEIGHT * YScale);
ScaleX = XScale;
ScaleY = YScale;
InitBitMap(&LocalBitMap,8,2 * FONT_WIDTH * ScaleX,2 * FONT_HEIGHT * ScaleY);
InitRastPort(&LocalRPort);
InitRastPort(&TempRPort);
SetDrMd(&TempRPort,JAM1);
if(LocalBitMap.Planes[0] = (PLANEPTR)AllocVec(LocalBitMap.Depth * LocalBitMap.BytesPerRow * LocalBitMap.Rows,MEMF_CHIP))
{
LONG PlaneSize = LocalBitMap.BytesPerRow * LocalBitMap.Rows;
WORD i;
for(i = 1 ; i < LocalBitMap.Depth ; i++)
LocalBitMap.Planes[i] = LocalBitMap.Planes[i - 1] + PlaneSize;
LocalRPort.BitMap = &LocalBitMap;
init_fonts();
ScreenToFront(Window->WScreen);
ActivateWindow(Window);
return(0);
}
ReleaseColours();
CloseWindow(Window);
Window = NULL;
if(Screen)
{
CloseScreen(Screen);
Screen = NULL;
}
}
return(-1);
}
VOID GfxDisplay::PutLine(STRPTR Line)
{
if(Line)
{
int i,bg,len;
bg = 32+4+PutIndex;
SetFgPen(bg);
Fill(0,PutIndex*(*fontheight)*ScaleY,DisplayWidth, (*fontheight)*ScaleY);
if((len = (int)strlen(Line)) > 40)
len = 40;
for(i = 0 ; i < len ; i++)
xputc(Line[i],0,i,PutIndex,0,0,0,0,7,bg);
PutIndex = (WORD)((PutIndex + 1) % (*rows));
}
else
{
PutIndex = 0;
xclearscreen();
}
}
void GfxDisplay::init_fonts()
{
static UBYTE raw_del[] = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f };
extern UBYTE raw_font[];
int n, i;
/* primary graphic, 2nd suppl. mosaic, suppl. graphic, 3rd suppl. mosaic */
for(n=0; n<4*96; n++) {
btx_font[n].raw = (UBYTE *)&raw_font[n*2*FONT_HEIGHT];
btx_font[n].bits = 1;
btx_font[n].link = NULL;
for(i=0; i<4; i++) btx_font[n].map[i] = NULL;
}
/* link chars into '1st supplementary mosaic' (L) set */
for(n=0; n<32; n++) {
btx_font[SUP1*96+n].link = btx_font+SUP2*96+n;
btx_font[SUP1*96+n+32].link = btx_font+PRIM*96+n+32;
btx_font[SUP1*96+n+64].link = btx_font+SUP2*96+n+64;
}
/* initialize the DEL character of the L set */
btx_font[L*96+0x7f-0x20].link = NULL;
btx_font[L*96+0x7f-0x20].raw = raw_del;
btx_font[L*96+0x7f-0x20].bits = 1;
for(i=0; i<4; i++) btx_font[L*96+0x7f-0x20].map[i] = NULL;
/* initialize DRCS font to all NULL's */
btx_font[DRCS*96+0].link = btx_font; /* link 'SPACE' */
for(n=1; n<96; n++) {
btx_font[DRCS*96+n].bits = 0;
btx_font[DRCS*96+n].raw = NULL;
btx_font[DRCS*96+n].link = NULL;
for(i=0; i<4; i++) btx_font[DRCS*96+n].map[i] = NULL;
}
}
void GfxDisplay::xputc(int c,int set,int x,int y,int xdouble,int ydouble,int underline,int diacrit,int fg,int bg)
{
btxchar *ch, *dia;
if(x<0 || y<0 || x>39 || y>(*rows)-1) return;
ch = btx_font + set*96 + c - 0x20;
/* folow the link pointer */
if(ch->link) ch = ch->link;
/* a yet undefined DRC should be drawn - draw a SPACE */
if(!ch->raw) ch = btx_font;
if(ch->bits==1) {
dia = diacrit ? &btx_font[SUPP*96 + diacrit - 0x20] : (btxchar *)NULL;
xdraw_normal_char(ch, x, y, xdouble, ydouble, underline, dia, fg, bg);
}
else { /* 2/4 bits */
xdraw_multicolor_char(ch, x, y, xdouble, ydouble);
}
}
void GfxDisplay::xdraw_normal_char(btxchar *ch,int x,int y,int xd,int yd,int ul,btxchar *dia,int fg,int bg)
{
int size;
if(fg==TRANSPARENT) fg = 32+4+y;
if(bg==TRANSPARENT) bg = 32+4+y;
if(fg != cur_fg)
{
PreparePaintFg(fg);
PreparePaintFgBg(fg,bg);
}
else
{
if(bg != cur_bg)
PreparePaintFgBg(fg,bg);
}
cur_fg = fg;
cur_bg = bg;
size = yd*2 + xd;
/* Pixmap not available in this size, create it */
if(!ch->map[size])
ch->map[size] = rawfont2bitmap(ch->raw, (xd+1),(yd+1));
if(dia && !dia->map[size])
dia->map[size] = rawfont2bitmap(dia->raw, (xd+1),(yd+1));
if(ch->map[size])
DrawTemplate(ch->map[size],FgBgMinterms,x*FONT_WIDTH*ScaleX, y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(*fontheight)*ScaleY*(yd+1));
if(dia && dia->map[size])
DrawTemplate(dia->map[size],FgMinterms,x*FONT_WIDTH*ScaleX, y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(*fontheight)*(yd+1)*ScaleY);
if(ul)
{
SetFgPen(fg);
Fill(x*FONT_WIDTH*ScaleX,y*(*fontheight)*ScaleY+((*fontheight)-1)*(yd+1)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(yd+1)*ScaleY);
}
}
void GfxDisplay::xdraw_multicolor_char(btxchar *ch,int x,int y,int xd,int yd)
{
int size;
size = yd*2 + xd;
if(!ch->map[size])
ch->map[size] = createpixmapfromfont(ch->raw, (xd+1),(yd+1), ch->bits );
if(ch->map[size])
DrawTemplate(ch->map[size],NULL,x*FONT_WIDTH*ScaleX, y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX*(xd+1),(*fontheight)*(yd+1)*ScaleY);
}
void GfxDisplay::xclearscreen()
{
int y, bg;
for(y=0; y<(*rows); y++)
{
bg = 32+4+y;
SetFgPen(bg);
Fill(0,y*(*fontheight)*ScaleY,DisplayWidth, (*fontheight)*ScaleY);
}
}
void GfxDisplay::xcursor(int x,int y)
{
Complement(x*FONT_WIDTH*ScaleX,y*(*fontheight)*ScaleY,FONT_WIDTH*ScaleX,(*fontheight)*ScaleY);
}
struct BitMap * GfxDisplay::rawfont2bitmap(UBYTE *src, int xzoom, int yzoom)
{
struct BitMap *Bits;
if(Bits = NewBitMap(1,FONT_WIDTH*ScaleX * xzoom,FONT_HEIGHT * yzoom * ScaleY))
{
if(src)
{
struct RastPort *RPort = &TempRPort;
int x,y;
UBYTE pattern;
RPort->BitMap = Bits;
Bits->Depth = 1;
SetRast(RPort,0);
SetAPen(RPort,1);
for(y = 0 ; y < FONT_HEIGHT * yzoom * ScaleY ; y++)
{
pattern = src[2 * (y / (yzoom*ScaleY))];
for(x = 0 ; x < (FONT_WIDTH / 2) * (xzoom*ScaleX) ; x++)
{
if(pattern & (1 << (5 - (x / (xzoom*ScaleX)))))
WritePixel(RPort,x,y);
}
pattern = src[2 * (y / (yzoom*ScaleY)) + 1];
for(x = 0 ; x < (FONT_WIDTH / 2) * xzoom*ScaleX ; x++)
{
if(pattern & (1 << (5 - (x / (xzoom*ScaleX)))))
WritePixel(RPort,x + (FONT_WIDTH / 2) * xzoom*ScaleX,y);
}
}
Bits->Depth = 8;
}
}
return(Bits);
}
struct BitMap * GfxDisplay::createpixmapfromfont(UBYTE *src,int xzoom,int yzoom,int bits)
{
UBYTE *d = data;
int c,i,j,k,l,x,y,byteindex;
struct BitMap *Bits;
if(Bits = NewBitMap(8,FONT_WIDTH*ScaleX * xzoom,FONT_HEIGHT * yzoom * ScaleY))
{
struct RastPort *RPort;
LONG LastPen = -1,ThisPen;
RPort = &TempRPort;
RPort->BitMap = Bits;
SetRast(RPort,0);
if(src)
{
for(y=0; y<FONT_HEIGHT; y++)
{
byteindex = 0;
for(l=0; l<2; l++)
{
for(x=5; x>=0; x--)
{
for(c=0, k=0; k<bits; k++)
{
if(*(src+k*FONT_HEIGHT*2) & (1<<x) )
c |= 1<<k;
}
for(j=0; j<xzoom*ScaleX; j++)
row[byteindex++] = (UBYTE)(bits==4 ? c+16 : c+32);
}
src++;
}
for(j=0; j<(yzoom*ScaleY); j++)
{
for(i=0; i<byteindex; i++)
*d++ = row[i];
}
}
d = data;
for(y = 0 ; y < FONT_HEIGHT * yzoom * ScaleY ; y++)
{
for(x = 0 ; x < FONT_WIDTH*ScaleX * xzoom ; x++)
{
ThisPen = Pen[*d++];
if(LastPen != ThisPen)
SetAPen(RPort,LastPen = ThisPen);
WritePixel(RPort,x,y);
}
}
}
}
return(Bits);
}
void GfxDisplay::define_raw_DRC(int c,UBYTE *data, int bits)
{
struct btxchar *ch = btx_font + DRCS*96 + c - 0x20;
int n;
if(ch->raw)
delete ch->raw;
for(n=0; n<4; n++)
{
if(ch->map[n])
{
DisposeBitMap(ch->map[n]);
ch->map[n] = NULL;
}
}
if(ch->raw = new UBYTE[2*FONT_HEIGHT*bits])
{
memset(ch->raw,0,2*FONT_HEIGHT*bits);
ch->bits = (UBYTE)bits;
for(n=0; n<2*FONT_HEIGHT*bits; n++)
ch->raw[n] = data[n];
ch->link = NULL;
}
}
void GfxDisplay::free_DRCS()
{
int i, n;
btx_font[DRCS*96+0].link = btx_font; /* link 'SPACE' */
for(n=DRCS*96+1; n<(DRCS+1)*96; n++)
{
if(btx_font[n].raw)
{
delete btx_font[n].raw;
btx_font[n].raw = NULL;
}
for(i=0; i<4; i++)
{
if(btx_font[n].map[i])
{
DisposeBitMap(btx_font[n].map[i]);
btx_font[n].map[i] = NULL;
}
btx_font[n].link = NULL;
btx_font[n].bits = 0;
}
}
}
void GfxDisplay::free_font_pixmaps()
{
int i, n;
for(n=0; n<6*96; n++)
{
if(!btx_font[n].link)
{
for(i=0; i<4; i++)
{
if(btx_font[n].map[i])
{
DisposeBitMap(btx_font[n].map[i]);
btx_font[n].map[i] = NULL;
}
}
}
}
}
void GfxDisplay::default_colors()
{
init_colormap();
store_colors();
}
void GfxDisplay::store_colors()
{
int n;
// for(n = 0 ; n < 16 ; n++)
// SetColour(n,colormap[n].red,colormap[n].green,colormap[n].blue);
for(n = 0 ; n < 8 ; n++)
{
SetColour(n + 16,colormap[n + 16].red,colormap[n + 16].green,colormap[n + 16].blue); // clut 2
SetColour(n + 24,colormap[n + 24].red,colormap[n + 24].green,colormap[n + 24].blue); // clut 3
}
for(n = 0 ; n < 4 ; n++) // dclut
SetColour(32 + n,colormap[32 + n].red,colormap[32 + n].green,colormap[32 + n].blue);
for(n = 0 ; n < 24 ; n++)
SetColour(32 + 4 + n,colormap[32 + 4 + n].red,colormap[32 + 4 + n].green,colormap[32 + 4 + n].blue);
}
void GfxDisplay::init_colormap()
{
int n;
/* clut 0 + clut 1 */
for(n=0; n<16; n++) { /* page 112) */
if(n==8) { colormap[n] = colormap[0]; continue; }
colormap[n].red = (UBYTE)(((n&1)>0) ? ( ((n&8)==0) ? 0xff : 0x7f ) : 0);
colormap[n].green = (UBYTE)(((n&2)>0) ? ( ((n&8)==0) ? 0xff : 0x7f ) : 0);
colormap[n].blue = (UBYTE)(((n&4)>0) ? ( ((n&8)==0) ? 0xff : 0x7f ) : 0);
}
/* clut 2 + clut 3 */
for(n=0; n<8; n++) {
colormap[n+16].red = colormap[n+24].red = (UBYTE)(n&1 ? 0xff : 0);
colormap[n+16].green = colormap[n+24].green = (UBYTE)(n&2 ? 0xff : 0);
colormap[n+16].blue = colormap[n+24].blue = (UBYTE)(n&4 ? 0xff : 0);
}
/* DCLUT */
for(n=0; n<4; n++) {
colormap[32+n].red = colormap[n].red;
colormap[32+n].green = colormap[n].green;
colormap[32+n].blue = colormap[n].blue;
dclut[n] = n;
}
/* fullrow background (BLACK) */
for(n=0; n<24; n++) {
colormap[32+4+n].red = colormap[0].red;
colormap[32+4+n].green = colormap[0].green;
colormap[32+4+n].blue = colormap[0].blue;
fullrow_bg[n] = 0;
}
}
void GfxDisplay::define_color(int index,int r,int g,int b) // 4 bit pro Eintrag
{
int i;
r &= 15;
g &= 15;
b &= 15;
r = (r << 4) | r;
g = (g << 4) | g;
b = (b << 4) | b;
colormap[index].red = (UBYTE)r;
colormap[index].green = (UBYTE)g;
colormap[index].blue = (UBYTE)b;
SetColour(index,r,g,b);
/* if DCLUT contains this color, change DCLUT color too */
for(i=0; i<4; i++)
{
if(dclut[i]==index)
define_DCLUT(i, index);
}
/* if fullrow_bg contains this color, change fullrow color too */
for(i=0; i<24; i++)
{
if(fullrow_bg[i]==index)
define_fullrow_bg(i, index);
}
}
void GfxDisplay::define_DCLUT(int entry,int index)
{
dclut[entry] = index;
colormap[32+entry].red = colormap[index].red;
colormap[32+entry].green = colormap[index].green;
colormap[32+entry].blue = colormap[index].blue;
SetColour(32 + entry,colormap[32 + entry].red,colormap[32 + entry].green,colormap[32 + entry].blue);
}
void GfxDisplay::define_fullrow_bg(int row,int index)
{
fullrow_bg[row] = index;
colormap[32+4+row].red = colormap[index].red;
colormap[32+4+row].green = colormap[index].green;
colormap[32+4+row].blue = colormap[index].blue;
SetColour(32 + 4 + row,colormap[32 + 4 + row].red,colormap[32 + 4 + row].green,colormap[32 + 4 + row].blue);
}
/******************************************************************************/
#define V0H0 (0)
#define V0H1 (NANBC | ANBNC | NANBC | ANBC)
#define V1H0 (NABNC | ABNC | NABC | ABC)
#define V1H1 (NANBC | NANBNC | NABC | NABNC | ANBC | ANBNC | ABC | ABNC)
#define PAINT_a (NANBC | ANBC | NABNC | ABNC | NABC | ABC)
#define PAINT_b (ANBC | NANBC)
VOID GfxDisplay::PreparePaintFgBg(UBYTE Fore,UBYTE Back,UBYTE *Minterms)
{
UBYTE Mask,Term,i;
if(!Minterms)
Minterms = FgBgMinterms;
Fore = (UBYTE)Pen[Fore];
Back = (UBYTE)Pen[Back];
for(i = 0 ; i < 8 ; i++)
{
Mask = (UBYTE)(1 << i);
if(Fore & Mask)
{
if(Back & Mask)
Term = V1H1;
else
Term = V1H0;
}
else
{
if(Back & Mask)
Term = V0H1;
else
Term = V0H0;
}
Minterms[i] = Term;
}
}
VOID GfxDisplay::PreparePaintFg(UBYTE Fore,UBYTE *Minterms)
{
UBYTE Mask,Term,i;
if(!Minterms)
Minterms = FgMinterms;
Fore = (UBYTE)Pen[Fore];
for(i = 0 ; i < 8 ; i++)
{
Mask = (UBYTE)(1 << i);
if(Fore & Mask)
Term = PAINT_a;
else
Term = PAINT_b;
Minterms[i] = Term;
}
}
VOID GfxDisplay::DrawTemplate(CONST struct BitMap *BitMap,CONST UBYTE *Minterms,UWORD Left,UWORD Top,UWORD Width,UWORD Height)
{
Left += Window->BorderLeft;
Top += Window->BorderTop;
if(Minterms)
{
if(DirectRender)
{
WORD i;
for(i = 0 ; i < 8 ; i++)
{
SetWriteMask(RPort,1 << i);
BltBitMapRastPort((struct BitMap *)BitMap,0,0,RPort,Left,Top,Width,Height,Minterms[i]);
}
SetWriteMask(RPort,~0);
}
else
{
WORD i;
SetRast(&LocalRPort,0);
ClipBlit(RPort,Left,Top,&LocalRPort,0,0,Width,Height,0xC0);
for(i = 0 ; i < 8 ; i++)
BltBitMap((struct BitMap *)BitMap,0,0,&LocalBitMap,0,0,Width,Height,Minterms[i],1 << i,NULL);
BltBitMapRastPort(&LocalBitMap,0,0,RPort,Left,Top,Width,Height,0xC0);
}
}
else
BltBitMapRastPort((struct BitMap *)BitMap,0,0,RPort,Left,Top,Width,Height,0xC0);
}
VOID GfxDisplay::DisposeBitMap(struct BitMap *Bits)
{
if(Bits)
{
FreeVec(Bits->Planes[0]);
FreeVec(Bits);
}
}
struct BitMap * GfxDisplay::NewBitMap(WORD Depth,WORD Width,WORD Height)
{
struct BitMap *Bits;
if(Bits = (struct BitMap *)AllocVec(sizeof(struct BitMap),MEMF_ANY))
{
InitBitMap(Bits,8,Width,Height);
if(Depth == 1)
{
if(Bits->Planes[0] = (PLANEPTR)AllocVec(Bits->BytesPerRow * Bits->Rows,MEMF_CHIP))
{
WORD i;
for(i = 1 ; i < 8 ; i++)
Bits->Planes[i] = Bits->Planes[0];
}
}
else
{
if(Bits->Planes[0] = (PLANEPTR)AllocVec(Depth * Bits->BytesPerRow * Bits->Rows,MEMF_CHIP))
{
LONG PlaneSize = Bits->BytesPerRow * Bits->Rows;
WORD i;
for(i = 1 ; i < Depth ; i++)
Bits->Planes[i] = Bits->Planes[i - 1] + PlaneSize;
}
}
if(Bits->Planes[0])
return(Bits);
else
FreeVec(Bits);
}
return(NULL);
}
VOID GfxDisplay::SetFgPen(LONG Index)
{
if(Index != FgPen)
{
FgPen = Index;
SetAPen(RPort,Pen[Index]);
}
}
VOID GfxDisplay::SetBgPen(LONG Index)
{
if(Index != BgPen)
{
BgPen = Index;
SetBPen(RPort,Pen[Index]);
}
}
VOID GfxDisplay::SetPens(LONG Fg,LONG Bg)
{
if(Fg != FgPen || Bg != BgPen)
{
FgPen = Fg;
BgPen = Bg;
SetABPenDrMd(RPort,Pen[Fg],Pen[Bg],JAM2);
}
}
VOID GfxDisplay::Fill(LONG Left,LONG Top,LONG Width,LONG Height)
{
if(Width > 0 && Height > 0)
{
Left += Window->BorderLeft;
Top += Window->BorderTop;
RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
}
}
VOID GfxDisplay::Complement(LONG Left,LONG Top,LONG Width,LONG Height)
{
if(Width > 0 && Height > 0)
{
Left += Window->BorderLeft;
Top += Window->BorderTop;
SetABPenDrMd(RPort,-1,0,JAM1 | COMPLEMENT);
RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
SetABPenDrMd(RPort,Pen[FgPen],Pen[BgPen],JAM2);
}
}
VOID GfxDisplay::SetColour(LONG Index,UBYTE Red,UBYTE Green,UBYTE Blue)
{
ULONG Table[1 + 3 + 1];
Table[0] = (1L << 16) | Pen[Index];
Table[1] = SPREAD(Red);
Table[2] = SPREAD(Green);
Table[3] = SPREAD(Blue);
Table[4] = 0;
LoadRGB32(VPort,Table);
}
ULONG GfxDisplay::WaitMask(VOID)
{
return(WindowMask);
}
LONG GfxDisplay::Waiting(VOID)
{
if(WaitingChar == -1)
{
struct IntuiMessage *Message;
while(Message = (struct IntuiMessage *)GetMsg(WindowPort))
{
if(Message->Class == IDCMP_RAWKEY)
{
if((WaitingChar = (WORD)MapKey(Message)) >= 0)
{
ReplyMsg((struct Message *)Message);
return(1);
}
}
else
{
if(Message->Class == IDCMP_CLOSEWINDOW)
{
ReplyMsg((struct Message *)Message);
WaitingChar = '\033';
return(1);
}
}
ReplyMsg((struct Message *)Message);
}
return(0);
}
else
return(1);
}
LONG GfxDisplay::GetChar(VOID)
{
if(WaitingChar == -1)
{
struct IntuiMessage *Message;
while(Message = (struct IntuiMessage *)GetMsg(WindowPort))
{
if(Message->Class == IDCMP_RAWKEY)
{
LONG Result = MapKey(Message);
ReplyMsg((struct Message *)Message);
return(Result);
}
else
{
if(Message->Class == IDCMP_CLOSEWINDOW)
{
ReplyMsg((struct Message *)Message);
return('\033');
}
}
ReplyMsg((struct Message *)Message);
}
return(-1);
}
else
{
LONG Result = WaitingChar;
WaitingChar = -1;
return(Result);
}
}
LONG GfxDisplay::MapKey(struct IntuiMessage *Message)
{
static LONG Table[][2] =
{
RAWKEY_CursorUp, KEY_CursorUp,
RAWKEY_CursorDown, KEY_CursorDown,
RAWKEY_CursorRight, KEY_CursorRight,
RAWKEY_CursorLeft, KEY_CursorLeft,
RAWKEY_Help, KEY_Help,
RAWKEY_F1, -1,
RAWKEY_F2, -1,
RAWKEY_F3, -1,
RAWKEY_F4, -1,
RAWKEY_F5, -1,
RAWKEY_F6, -1,
RAWKEY_F7, -1,
RAWKEY_F8, -1,
RAWKEY_F9, -1,
RAWKEY_F10, -1,
-1
};
UBYTE Buffer[10];
WORD i;
for(i = 0 ; Table[i][0] != -1 ; i++)
{
if((Message->Code & ~IECODE_UP_PREFIX) == Table[i][0])
{
if(Message->Code & IECODE_UP_PREFIX)
return(-1);
else
return(Table[i][1]);
}
}
Event.ie_Class = IECLASS_RAWKEY;
Event.ie_SubClass = 0;
Event.ie_Code = Message->Code;
Event.ie_Qualifier = Message->Qualifier;
Event.ie_EventAddress = (APTR *) *((ULONG *)Message->IAddress);
Buffer[0] = 0;
if(MapRawKey(&Event,(char *)&Buffer[0],10,(struct KeyMap *)NULL) > 0)
return(Buffer[0]);
else
return(-1);
}
ULONG GfxDisplay::FindBestModeID(Tag FirstTag,...)
{
struct TagItem *List,
*Item;
ULONG Mode;
ULONG BestMode;
LONG BestWidth,
BestHeight,
BestDepth;
ULONG MustHave,
MustNotHave;
ULONG MonitorID;
struct ViewPort *ViewPort;
ULONG SourceID;
UWORD NominalWidth,
NominalHeight;
UWORD DesiredWidth,
DesiredHeight;
UBYTE Depth;
UBYTE RedBits;
UBYTE BlueBits;
UBYTE GreenBits;
struct DisplayInfo DisplayInfo;
struct DimensionInfo DimensionInfo;
LONG Width,
Height;
MustHave = NULL;
MustNotHave = SPECIAL_FLAGS;
Depth = 1;
MonitorID = INVALID_ID;
SourceID = INVALID_ID;
RedBits = 4;
BlueBits = 4;
GreenBits = 4;
NominalWidth = 640,
NominalHeight = 200;
List = (struct TagItem *)&FirstTag;
while(Item = NextTagItem(&List))
{
switch(Item->ti_Tag)
{
case BIDTAG_DIPFMustHave:
MustHave = Item->ti_Data;
break;
case BIDTAG_DIPFMustNotHave:
MustNotHave = Item->ti_Data;
break;
case BIDTAG_RedBits:
RedBits = (UBYTE)Item->ti_Data;
break;
case BIDTAG_GreenBits:
GreenBits = (UBYTE)Item->ti_Data;
break;
case BIDTAG_BlueBits:
BlueBits = (UBYTE)Item->ti_Data;
break;
case BIDTAG_MonitorID:
MonitorID = Item->ti_Data;
break;
case BIDTAG_NominalWidth:
NominalWidth = (UWORD)Item->ti_Data;
break;
case BIDTAG_NominalHeight:
NominalHeight = (UWORD)Item->ti_Data;
break;
}
}
DesiredWidth = NominalWidth;
DesiredHeight = NominalHeight;
List = (struct TagItem *)&FirstTag;
if(ViewPort = (struct ViewPort *)GetTagData(BIDTAG_ViewPort,NULL,List))
{
NominalWidth = ViewPort->DWidth;
NominalHeight = ViewPort->DHeight;
DesiredWidth = NominalWidth;
DesiredHeight = NominalHeight;
Depth = ViewPort->RasInfo->BitMap->Depth;
SourceID = GetVPModeID(ViewPort);
}
if(Item = FindTagItem(BIDTAG_SourceID,List))
{
if(GetDisplayInfoData((APTR)NULL,(UBYTE *)&DisplayInfo,sizeof(DisplayInfo),DTAG_DISP,SourceID))
MustHave = (DisplayInfo.PropertyFlags & SPECIAL_FLAGS) | MustHave;
else
return(INVALID_ID);
if(GetDisplayInfoData((APTR)NULL,(UBYTE *)&DimensionInfo,sizeof(DimensionInfo),DTAG_DIMS,SourceID))
{
NominalWidth = (UWORD)(DimensionInfo.Nominal.MaxX - DimensionInfo.Nominal.MinX + 1);
NominalHeight = (UWORD)(DimensionInfo.Nominal.MaxY - DimensionInfo.Nominal.MinY + 1);
DesiredWidth = NominalWidth;
DesiredHeight = NominalHeight;
}
else
return(INVALID_ID);
}
List = (struct TagItem *)&FirstTag;
while(Item = NextTagItem(&List))
{
switch(Item->ti_Tag)
{
case BIDTAG_DesiredWidth:
DesiredWidth = (UWORD)Item->ti_Data;
break;
case BIDTAG_DesiredHeight:
DesiredHeight = (UWORD)Item->ti_Data;
break;
case BIDTAG_Depth:
Depth = (UBYTE)Item->ti_Data;
break;
}
}
BestMode = INVALID_ID;
BestWidth = 0;
BestHeight = 0;
BestDepth = 0;
Mode = INVALID_ID;
while((Mode = NextDisplayInfo(Mode)) != INVALID_ID)
{
if(MonitorID != INVALID_ID)
{
if((Mode & MONITOR_ID_MASK) != MonitorID)
continue;
}
if(ModeNotAvailable(Mode) & ~DI_AVAIL_NOTWITHGENLOCK)
continue;
if(GetDisplayInfoData((APTR)NULL,(UBYTE *)&DisplayInfo,sizeof(DisplayInfo),DTAG_DISP,Mode) && GetDisplayInfoData((APTR)NULL,(UBYTE *)&DimensionInfo,sizeof(DimensionInfo),DTAG_DIMS,Mode))
{
if(DimensionInfo.MaxDepth < Depth || DisplayInfo.RedBits < RedBits || DisplayInfo.GreenBits < GreenBits || DisplayInfo.BlueBits < BlueBits)
continue;
if(DimensionInfo.MaxDepth > 8 && Depth <= 8)
continue;
if(MustHave)
{
if((DisplayInfo.PropertyFlags & MustHave) != MustHave)
continue;
}
if(MustNotHave)
{
if(DisplayInfo.PropertyFlags & MustNotHave)
continue;
}
Width = DimensionInfo.TxtOScan.MaxX - DimensionInfo.TxtOScan.MinX + 1;
Height = DimensionInfo.TxtOScan.MaxY - DimensionInfo.TxtOScan.MinY + 1;
if(DesiredWidth <= Width && DesiredHeight <= Height && NominalWidth <= DimensionInfo.Nominal.MaxX - DimensionInfo.Nominal.MinX + 1 && NominalHeight <= DimensionInfo.Nominal.MaxY - DimensionInfo.Nominal.MinY + 1)
{
if(!BestWidth || !BestHeight || !BestDepth)
{
BestMode = Mode;
BestDepth = DimensionInfo.MaxDepth;
BestWidth = DesiredWidth;
BestHeight = DesiredHeight;
}
else
{
if(DimensionInfo.MaxDepth <= BestDepth && Width <= BestWidth && Height <= BestHeight)
{
BestMode = Mode;
BestDepth = DimensionInfo.MaxDepth;
BestWidth = DesiredWidth;
BestHeight = DesiredHeight;
}
}
}
}
}
return(BestMode);
}
VOID GfxDisplay::ReleaseColours(VOID)
{
WORD i;
for(i = 0 ; i < 60 ; i++)
{
if(Pen[i] != -1)
{
ReleasePen(VPort->ColorMap,Pen[i]);
Pen[i] = -1;
}
}
}
BOOL GfxDisplay::InitColours(VOID)
{
int n;
init_colormap();
for(n = 0 ; n < 16 ; n++)
{
Pen[n] = (LONG)ObtainBestPen(VPort->ColorMap,SPREAD(colormap[n].red),SPREAD(colormap[n].green),SPREAD(colormap[n].blue),
OBP_Precision, PRECISION_IMAGE,
OBP_FailIfBad, TRUE,
TAG_DONE);
if(Pen[n] == -1)
{
ReleaseColours();
return(FALSE);
}
}
for(n = 16 ; n < 60 ; n++)
{
Pen[n] = (LONG)ObtainPen(VPort->ColorMap,-1, 0,0,0, PEN_EXCLUSIVE|PEN_NO_SETCOLOR);
if(Pen[n] == -1)
{
ReleaseColours();
return(FALSE);
}
}
for(n = 0 ; n < 8 ; n++)
{
SetColour(n + 16,colormap[n + 16].red,colormap[n + 16].green,colormap[n + 16].blue); // clut 2
SetColour(n + 24,colormap[n + 24].red,colormap[n + 24].green,colormap[n + 24].blue); // clut 3
}
for(n = 0 ; n < 4 ; n++) // dclut
SetColour(32 + n,colormap[32 + n].red,colormap[32 + n].green,colormap[32 + n].blue);
for(n = 0 ; n < 24 ; n++)
SetColour(32 + 4 + n,colormap[32 + 4 + n].red,colormap[32 + 4 + n].green,colormap[32 + 4 + n].blue);
return(TRUE);
}